/*
 *  Copyright 2008 Danny Lagrouw
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License. 
 */
package org.bastion.message;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * DomainMessage indicating that an object in the domain needs the value of a
 * configurable property. This value can either be a map of name/value pairs, a
 * collection (containing only the values) or a single value. Properties can be
 * requested with a filter.
 * 
 * @author Danny
 */
public class GetConfigMessage implements DomainMessage {

	private String propertyName;

	private Pattern propertyFilter;

	private Map<String, ? extends Object> resultMap;

	private Object singleResult;

	/**
	 * Creates a message to request a single property with the specified name.
	 * 
	 * @param propertyName
	 */
	public GetConfigMessage(String propertyName) {
		this.propertyName = propertyName;
	}

	/**
	 * Creates a message to request a set of properties with names matching the
	 * specified filter.
	 * 
	 * @param propertyFilter
	 */
	public GetConfigMessage(Pattern propertyFilter) {
		this.propertyFilter = propertyFilter;
	}

	public Pattern getPropertyFilter() {
		return propertyFilter;
	}

	public String getPropertyName() {
		return propertyName;
	}

	/**
	 * Specifies a map containing property names and values.
	 * 
	 * @param resultMap
	 */
	@SuppressWarnings("unchecked")
	public void setResultMap(Map<String, ? extends Object> resultMap) {
		this.resultMap = (Map<String, ? extends Object>) (resultMap == null ? Collections.emptyMap() : resultMap);
	}

	/**
	 * Sets the single property value retrieved by a service.
	 * 
	 * @param value
	 */
	public void setSingleResult(Object value) {
		singleResult = value;
	}

	/**
	 * Returns a map containing property names and values.
	 * 
	 * @return
	 */
	public Map<String, ? extends Object> getResultMap() {
		return resultMap;
	}

	/**
	 * Returns a collection containing property values.
	 * 
	 * @return
	 */
	public Collection<? extends Object> getResultCollection() {
		return resultMap == null ? null : resultMap.values();
	}

	/**
	 * Returns the first property value found. If the specified
	 * {@link #propertyFilter} returns more than one value, it is not guaranteed
	 * that any of these values will be returned as the first one.
	 * 
	 * @return the first property value found, or <code>null</code> if no
	 *         properties were found.
	 */
	public Object getSingleResult() {
		if (singleResult != null) {
			return singleResult;
		}
		return (resultMap == null || resultMap.isEmpty()) ? null : resultMap.values().iterator().next();
	}

}
